package model

import (
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"path/filepath"

	"torler.com/qingyue/common/types"
)

type RawBook struct {
	Id             types.TableId    `gorm:"column:id;primaryKey;autoIncrement"`                               //自增ID,主键,自动递增,创建时忽略
	BookId         types.TableId    `gorm:"column:book_id;default:0"`                                         //应正式库小说的Id：在匹配成功时赋值
	SourceId       types.SourceId   `gorm:"column:source;type:tinyint;index:idx_rawbook_2"`                   //来源站点
	OId            types.OriginId   `gorm:"column:oid;type:varchar(32);index:idx_rawbook_2"`                  //来源章节Id
	BookName       string           `gorm:"column:book_name;type:varchar(50);index:idx_rawbook_1"`            //小说名
	Author         string           `gorm:"column:author;type:varchar(20);index:idx_rawbook_1"`               //作者
	WriteState     types.WriteState `gorm:"column:write_state;type:tinyint(1);default:0"`                     //写作状态
	CategoryName   string           `gorm:"column:category_name;type:varchar(20)"`                            //小说分类
	Desc           string           `gorm:"column:desc;type:text"`                                            //小说简介
	ImgUrl         string           `gorm:"column:img_url;type:varchar(255)"`                                 //封面
	Chapters       JSONRawChapters  `gorm:"column:chapters;type:json"`                                        // 章节列表
	MetaState      types.MetaState  `gorm:"column:meta_state;type:tinyint(1);default:0;index:idx_lbi_search"` //基本信息状态
	ChapterCount   int              `gorm:"column:chapter_count;type:int;default:0"`                          //章节数量
	Extra          string           `gorm:"column:extra;type:json"`                                           //扩展字段:json方式存放的
	LastUpdateTime sql.NullTime     `gorm:"column:last_utime;type:datetime(0)"`
	types.Basic
	types.SpateInfo
}

func NewRawBook(sourceId types.SourceId, oId types.OriginId) *RawBook {
	return &RawBook{
		SourceId: sourceId,
		OId:      oId,
	}
}

func (RawBook) TableName() string {
	return "sp_raw_book"
}

func (it *RawBook) GetExtraAsImportedExtra() *ImportedExtra {
	var extra ImportedExtra
	err := json.Unmarshal([]byte(it.Extra), &extra)
	if err != nil {
		return nil
	}
	return &extra
}
func (it *RawBook) SetExtra(extra any) {
	if extra == nil {
		return
	}
	bytes, err := json.Marshal(extra)
	if err != nil {
		return
	}
	it.Extra = string(bytes)
}

type RawChapter struct {
	Oid         types.OriginId `json:"oid"`            //源站章节id
	ChapterName string         `json:"chapter_name"`   //章节名
	Path        string         `json:"path,omitempty"` //章节路径
	Content     string         `json:"-"`              //章节内容
}

func NewRawChapter(oId types.OriginId, chapterName string) *RawChapter {
	return &RawChapter{
		Oid:         oId,
		ChapterName: chapterName,
	}
}

// 实现Scanner接口用于从数据库读取JSON
func (cc *RawChapter) Scan(value interface{}) error {
	if value == nil {
		return nil
	}

	bytes, ok := value.([]byte)
	if !ok {
		return nil
	}

	return json.Unmarshal(bytes, cc)
}

// 为指针类型实现Valuer接口用于将数据写入数据库时转换为JSON
func (cc *RawChapter) Value() (driver.Value, error) {
	if cc == nil {
		return nil, nil
	}
	return json.Marshal(cc)
}

// JSONCChapters 是自定义类型，用于处理章节列表的JSON序列化
type JSONRawChapters []*RawChapter

// 实现Scanner接口用于从数据库读取JSON
func (j *JSONRawChapters) Scan(value interface{}) error {
	if value == nil {
		*j = nil
		return nil
	}

	bytes, ok := value.([]byte)
	if !ok {
		return nil
	}

	return json.Unmarshal(bytes, j)
}

// 实现Valuer接口用于将数据写入数据库时转换为JSON
func (j JSONRawChapters) Value() (driver.Value, error) {
	if j == nil {
		return nil, nil
	}
	return json.Marshal(j)
}

type ImportedExtra struct {
	ImportVersion int8   `json:"import_version"`
	FileName      string `json:"file_name"`
	FilePath      string `json:"file_path"`
	FileSize      int    `json:"file_size"`
}

func NewImportedExtra(version int, path string) *ImportedExtra {
	return &ImportedExtra{
		FilePath:      path,
		FileName:      filepath.Base(path),
		ImportVersion: int8(version),
	}
}

func (ie *ImportedExtra) Scan(value interface{}) error {
	if value == nil {
		return nil
	}

	bytes, ok := value.([]byte)
	if !ok {
		return nil
	}

	return json.Unmarshal(bytes, ie)
}
func (ie *ImportedExtra) Value() (driver.Value, error) {
	if ie == nil {
		return nil, nil
	}
	return json.Marshal(ie)
}
